package com.metamech.vorpal;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

import org.apache.log4j.Logger;

import com.metamech.jabber.Authenticator;
import com.metamech.jabber.Session;
import com.metamech.jabber.xml.PacketQueue;
import com.metamech.jabber.xml.ProcessThread;
import com.metamech.jabber.xml.QueueThread;
import com.metamech.log.Log;
import com.metamech.vorpal.handler.AuthHandler;
import com.metamech.vorpal.handler.CloseStreamHandler;
import com.metamech.vorpal.handler.MessageHandler;
import com.metamech.vorpal.handler.OpenStreamHandler;
import com.metamech.vorpal.handler.PresenceHandler;
import com.metamech.vorpal.handler.RegisterHandler;
import com.metamech.vorpal.handler.RosterHandler;


public class Server extends Thread {

	final static public int    JABBER_PORT = 5222;
	final static public String SERVER_NAME = "mobbuzz.com";
	private static Logger logger=Logger.getLogger(Server.class);
	// Create the global data structures everyone works with
	PacketQueue packetQueue = new PacketQueue();
	UserIndex index = new UserIndex();
	//SessionIndex index = new SessionIndex();

	public void startListening(){

		createQueueThread();
		ServerSocket serverSocket;

		try {
			// Create the server socket to listen to
			serverSocket = new ServerSocket(JABBER_PORT);
		} catch (IOException ex){
			// This is likely an very bad problem...
			// ... probably can't use the port...
			// ... report the problem and quit
			logger.info(ex.getStackTrace());
			ex.printStackTrace();
			return;
		}

		// We accept incoming sockets and start new threads forever
		while (true){
			try {
				// Wait for the connection
				Socket newSock = serverSocket.accept();
				Session session = new Session(newSock);

				// Spin off a new thread to handle the connection
				ProcessThread processor = new ProcessThread(packetQueue,session);
				processor.start();
			} catch (IOException ie){
				logger.info(ie.getStackTrace());
				ie.printStackTrace();
			}
		}
	}

	void createQueueThread(){
		// Create the Queue worker thread to process packets in the packet queue
		QueueThread qThread = new QueueThread(packetQueue);
		qThread.setDaemon(true);
		qThread.addListener(new OpenStreamHandler(index),"stream:stream");
	    qThread.addListener(new CloseStreamHandler(index),"/stream:stream");
	    qThread.addListener(new MessageHandler(index),"message");
	    qThread.addListener(new PresenceHandler(index),"presence");
	    qThread.addListener(new RegisterHandler(index),"jabber:iq:register");
	    qThread.addListener(new AuthHandler(index),"jabber:iq:auth");	    
	    qThread.addListener(new RosterHandler(index),"jabber:iq:roster");
		qThread.start();
	}

	public void run(){
		//System.out.print("Initializing authenticator...");
		logger.info("Initializing authenticator...");
	    Authenticator.randomToken();
	    logger.info("initialized.");
	    logger.info("Jabber Server -- " + SERVER_NAME + ":"+ JABBER_PORT);
	    startListening();
	}
	
	static public void main(String [] args){
		new Server().run();
	}
}
